#ifndef GAMEENGINE_GRAPHICS_LIGHTING_LIGHT_H
#define GAMEENGINE_GRAPHICS_LIGHTING_LIGHT_H

#include <GameEngine/Graphics/graphics_settings.h>

#include <GameEngine/Geometry/Location/point3d.h>
#include <GameEngine/Geometry/Core/angle.h>
#include <GameEngine/Core/Color/color_rgb.h>

#include <QtCore/QFlags>

#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//! Implements one single light
/*!
 *  This class allows to represent both infinite directional lights, point lights
 *  and spot lights. Infinite directional lights can be defined by setting the
 *  infinite flag to true (using the infinite() function). Conversely, point lights
 *  can be defined by setting the infinite flag to false; furthermore, the point
 *  light can be defined as a spot light by changing the light cutoff (using the
 *  set_spot_cutoff() function).
 *
 *  The parameters of the light are applied only if they are activated on the Light
 *  object. This limits the number of OpenGL calls - but unfortunately, all parameters
 *  of the light have to be stored, which makes the Light object inefficient in
 *  memory. One way to work around this issue would be to store dynamic data.
 */
class _Graphics_decl Light {

public:
	//! Enumerates which parameters are enabled on the light
	enum LightParameter {
		//! Define the ambient color of the light
		AmbientLight              = 1,
		//! Define the diffuse color of the light
		DiffuseLight              = 2,
		//! Define the specular color of the light
		SpecularLight             = 4,
		//! Define the spot direction of the light
		SpotDirectionLight        = 8,
		//! Define the spot exponent of the light
		SpotExponentLight         = 16,
		//! Define the spot cutoff of the light
		SpotCutoffLight           = 32,
		//! Define the constant attenuation of the light
		AttenuationConstantLight  = 64,
		//! Define the linear attenuation of the light
		AttenuationLinearLight    = 128,
		//! Define the quadratic attenuation of the light
		AttenuationQuadraticLight = 256
	};

	Q_DECLARE_FLAGS(LightParameters,LightParameter)

public:
	Light();
	Light(const Light& rhs);
	virtual ~Light();
	Light& operator=(const Light& rhs);

	const Point3d<float>& position() const;
	Point3d<float>& position();

	bool infinite() const;
	bool& infinite();

	const ColorRGBA& ambient_color() const;
	void set_ambient_color(const ColorRGBA& ambient);
	const ColorRGBA& diffuse_color() const;
	void set_diffuse_color(const ColorRGBA& diffuse);
	const ColorRGBA& specular_color() const;
	void set_specular_color(const ColorRGBA& specular);

	const Vector3d<float>& spot_direction() const;
	void set_spot_direction(const Vector3d<float>& direction);
	float spot_exponent() const;
	void set_spot_exponent(float exponent);
	const Angle<float>& spot_cutoff() const;
	void set_spot_cutoff(const Angle<float>& cutoff);

	float constant_attenuation() const;
	void set_constant_attenuation(float attenuation);
	float linear_attenuation() const;
	void set_linear_attenuation(float attenuation);
	float quadratic_attenuation() const;
	void set_quadratic_attenuation(float attenuation);

	bool active_parameter(LightParameter parameter) const;
	bool set_active_parameter(LightParameter parameter, bool enable=true);

	void apply_light(int light_index = 0) const;

protected:
	//! Position of the light source
	GAMEENGINE_DLL_CLASS(Point3d<float>) position_;

	//! Define wheter light source should be positional or infinite
	bool infinite_;

	//! Parameters activated on the light
	LightParameters parameters_;

	//! Ambient color of the light source
	ColorRGBA acolor_;
	//! Diffuse color of the light source
	ColorRGBA dcolor_;
	//! Specular color of the light source
	ColorRGBA scolor_;

	//! Spot direction of the light source
	GAMEENGINE_DLL_CLASS(Vector3d<float>) spot_direction_;
	//! Spot exponent of the light source
	float spot_exponent_;
	//! Spot cutoff of the light source
	GAMEENGINE_DLL_CLASS(Angle<float>) spot_cutoff_;

	//! Constant attenuation of the light source
	float constant_attenuation_;
	//! Linear attenuation of the light source
	float linear_attenuation_;
	//! Quadratic attenuation of the light source
	float quadratic_attenuation_;
};


//========================================================


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#endif
